#ifdef SU1
#define _GLIBCXX_DEBUG
#endif

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <stack>
#include <set>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define forl(i, n) for (int i = 1; i <= int(n); i++)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i, l, r) for (int i = int(l); i <= int(r); i++)
#define pb(a) push_back(a)
#define mp(x, y) make_pair((x), (y))
#define sz(a) (int) (a).size()
#define all(a) (a).begin(), (a).end()
#define ft first
#define sc second
#define x first
#define y second

template<typename X> inline X abs(const X& a) { return a < 0 ? -a : a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

const int INF = int(1e9);
const li INF64 = li(1e18);
const ld PI = acosl(ld(-1));
const ld EPS = 1e-9;

pt operator -(const pt& a, const pt& b) {
	return pt(a.x - b.x, a.y - b.y);
}
ld dot(const pt& a, const pt& b) {
	return a.x * b.x + a.y * b.y;
}
ld len(const pt& v) {
	return sqrtl(dot(v, v));
}

ld getAng(const pt& a, const pt& b, const pt& c) {
	pt v1 = b - a, v2 = c - b;
	ld len1 = len(v1), len2 = len(v2);
	ld cs = dot(v1, v2) / len1 / len2;
	return acosl(max(ld(-1), min(ld(1), cs)));
}

const int N = 100500;
int n, m;
pt pos[N];
vector<int> g[N];

ld getAng(int i, int j, int k) {
	ld ang = getAng(pos[i], pos[j], pos[k]);
//	cerr << i << ' ' << j << ' ' << k << " = " << ang << endl;
	return ang;
}

inline bool read()
{
	assert(scanf("%d%d", &n, &m) == 2);
	forn(i, n)
		assert(scanf("%d%d", &pos[i].x, &pos[i].y) == 2);
	forn(i, m) {
		int a, b;
		assert(scanf("%d%d", &a, &b) == 2);
		g[a].pb(b);
		g[b].pb(a);
	}
	return true;
}

ld initCost[N];
map<int,int> go[N];
int curCol;
map<pt,bool> used;
map<pt, int> col;

void dfs(int v, int to) {
	if (used[pt(v, to)]) return;
	used[pt(v, to)] = used[pt(to, v)] = true;
	col[pt(v, to)] = col[pt(to, v)] = curCol;
	dfs(to, go[to][v]);
}

int dsu[N];
int root(int v) {
	if (dsu[v] == v) return v;
	return dsu[v] = root(dsu[v]);
}
bool merge(int a, int b) {
	a = root(a); b = root(b);
	if (a == b) return false;
	if (rand() & 1) swap(a, b);
	dsu[a] = b;
	return true;
}

inline void solve()
{
	ld ans = 0;
	forn(v, n) {
		assert(sz(g[v]) == 2 || sz(g[v]) == 4);
		if (sz(g[v]) == 2) {
			ans += getAng(g[v][0], v, g[v][1]);
			go[v][g[v][0]] = g[v][1];
			go[v][g[v][1]] = g[v][0];
		} else {
			pair<ld,int> curMn(1e100, -1);
			for (int i = 1; i < 4; i++) {
				ld cur = getAng(g[v][0], v, g[v][i]);
				vector<int> nx;
				forn(j, 4) {
					if (j != 0 && j != i)
						nx.pb(g[v][j]);
				}
				cur += getAng(nx[0], v, nx[1]);
				if (cur < curMn.x) {
					curMn = min(curMn, mp(cur, i));
					go[v][g[v][0]] = g[v][i];
					go[v][g[v][i]] = g[v][0];
					go[v][nx[0]] = nx[1];
					go[v][nx[1]] = nx[0];
				}
			}
			ans += curMn.x;
			initCost[v] = curMn.x;
		}
	}
	forn(v, n) {
		forn(j, sz(g[v])) {
			int to = g[v][j];
			if (!used[pt(v, to)]) {
				curCol++;
				dfs(v, to);
			}
		}
	}
	vector<pair<ld,pt> > es;
	forn(v, n) {
		if (sz(g[v]) == 2) continue;
		int gg = go[v][g[v][0]];
		int opp = 3;
		if (gg == opp)
			opp = 2;
			
		int col1 = col[pt(v, g[v][0])];
		int col2 = col[pt(v, g[v][opp])];
		if (col1 == col2) continue;
		
		vector<int> vs1;
		vs1.pb(g[v][0]);
		vs1.pb(gg);
		
		vector<int> vs2;
		vs2.pb(g[v][opp]);
		vs2.pb(go[v][g[v][opp]]);
		
		ld cost = 1e100;
		forn(i, 2) {
			ld cur = getAng(vs1[0], v, vs2[i]) + getAng(vs1[1], v, vs2[i ^ 1]) - initCost[v];
			cost = min(cur, cost);
		}
		
		es.pb(mp(cost, pt(col1, col2)));
	}
	forn(i, curCol)
		dsu[i] = i;
	sort(all(es));
	forn(i, sz(es)) {
		if (merge(es[i].y.x, es[i].y.y))
			ans += es[i].x;
	}
	printf("%.10lf\n", double(ans));
}

int main()
{
#ifdef SU1
	assert(freopen("input.txt", "rt", stdin));
//	assert(freopen("output.txt", "wt", stdout));
#endif

	cout << fixed << setprecision(10);
	cerr << fixed << setprecision(5);

	assert(read());
	solve();
	
#ifdef SU1
	cerr << "=== TIME : " << clock() << " ===" << endl;
#endif
	return 0;
}
